﻿
namespace ObjectPool
{
    /// <summary>
    /// 对象池。只能管理实现了 <see cref="IManaged"/> 接口的对象。
    /// </summary>
    /// <typeparam name="T">被管理的对象，需要实现 <see cref="IManaged"/> 接口</typeparam>
    public interface IObjectPool<T> where T : IManaged
    {
        /// <summary>
        /// 对象池中的可用对象数量
        /// </summary>
        int Count { get; }

        /// <summary>
        /// 对象池的容量
        /// </summary>
        int Capacity { get; }

        /// <summary>
        /// 存入对象，该方法应该在对象第一次添加进池中时调用。
        /// 将对象放入池中前会调用被管理对象的 <see cref="IManaged.Init"/> 方法。
        /// 若被管理的对象实现了 <see cref="IManagedEvent"/> 接口，<see cref="IManagedEvent.OnStore"/> 会被调用
        /// </summary>
        /// <param name="managedObject">待管理的对象</param>
        /// <returns>存储成功时返回true</returns>
        bool Store(T managedObject);

        /// <summary>
        /// 取出对象，取出的对象可以使用 <see cref="Restore(T)"/> 重新放回池中，或者使用 <see cref="Release(T)"/> 彻底释放该对象。
        /// 若被管理的对象实现了 <see cref="IManagedEvent"/> 接口，<see cref="IManagedEvent.OnExtract"/> 会被调用
        /// </summary>
        /// <returns>若对象池中没有可用的对象时返回null</returns>
        T Extract();

        /// <summary>
        /// 重新存入对象，该方法应该在调用过 <see cref="Extract"/> 方法取出的对象重新放入池中时调用，
        /// 调用该方法会触发 <see cref="IManaged"/> 中的 <see cref="IManaged.Clear"/> 方法。
        /// 若被管理的对象实现了 <see cref="IManagedEvent"/> 接口，<see cref="IManagedEvent.OnRestore"/> 会被调用
        /// </summary>
        /// <param name="managedObject">待管理的对象</param>
        /// <returns>存储成功时返回true</returns>
        bool Restore(T managedObject);

        /// <summary>
        /// 释放从池中取出的对象。若被管理的对象实现了 <see cref="IManagedEvent"/> 接口，<see cref="IManagedEvent.OnRelease"/> 会被调用
        /// </summary>
        /// <param name="managedObject">池中取出的对象，若该对象未从对象池中取出，该方法不会释放对象</param>
        void Release(T managedObject);

        /// <summary>
        /// 尝试释放可释放的对象，该方法可以用于定期清理池中的对象。
        /// 若被管理的对象实现了 <see cref="IManagedEvent"/> 接口，<see cref="IManagedEvent.OnRelease"/> 会被调用
        /// </summary>
        void Release();

        /// <summary>
        /// 释放所有管理的对象，该方法会触发 <see cref="IManaged"/> 中的 <see cref="IManaged.Clear"/> 方法。
        /// 若被管理的对象实现了 <see cref="IManagedEvent"/> 接口，<see cref="IManagedEvent.OnRelease"/> 会被调用
        /// </summary>
        void Clear();
    }
}


